package com.bascker.algorithm.base.stack.impl;

import com.bascker.algorithm.base.stack.Stack;

import java.util.Iterator;
import java.util.function.Consumer;

/**
 * Fixed Capacity Stack
 *
 * @param <T>
 */
public class FixedStack<T> implements Stack<T> {

    private int n;

    private final T[] container;

    public FixedStack(final int capacity) {
        this.container = (T[]) new Object[capacity];
    }

    @Override
    public void push(final T item) {
        container[n++] = item;
    }

    @Override
    public T pop() {
        final T item = container[--n];
        container[n] = null;
        return item;
    }

    @Override
    public int size() {
        return n;
    }

    @Override
    public boolean isEmpty() {
        return n == 0;
    }

    @Override
    public T peek() {
        return container[n - 1];
    }

    @Override
    public Stack<T> copy() {
        final Stack<T> duplicate = new FixedStack<>(n);
        final Consumer<T> action = duplicate::push;
        forEach(action);

        return duplicate;
    }

    public boolean isFull() {
        return n == container.length;
    }

    @Override
    public Iterator<T> iterator() {
        return new FixedStackIterator();
    }

    class FixedStackIterator implements Iterator<T> {

        private int index = n - 1;

        @Override
        public boolean hasNext() {
            return index > -1;
        }

        @Override
        public T next() {
            return container[index--];
        }
    }

}